package com.tangyee.home_exercise_step.service;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.tangyee.home_exercise_step.config.Constant;
import com.tangyee.home_exercise_step.utils.CountDownTimer;
import com.tangyee.R;
import com.tangyee.home_exercise_step.StepActivity;
import com.tangyee.home_exercise_step.bean.NormalStepData;
import com.tangyee.home_exercise_step.bean.StepData;

import org.litepal.LitePal;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class StepService extends Service implements SensorEventListener {

    //StepService
    private final String TAG = "TAG_StepService";
    //默认30秒进行一次存储
    private static int duration = 5000;
    //当前的日期
    private static String CURRENTDATE = "";
    //传感器管理者
    private SensorManager sensorManager;

    private StepDetector stepDetector;
    private NotificationManager notificationManager;
    private NotificationCompat.Builder builder;
    private Messenger messenger = new Messenger(new MessengerHandler());

    //广播
    private BroadcastReceiver mBatInfoReceiver;
    private PowerManager.WakeLock wakeLock;
    private TimeCount timeCount;

    //计步传感器类型 0 - counter，1 - detector，2 - 加速度传感器
    private static int stepSensor = -1;
    private List<StepData> stepData;

    //用于计步传感器
    private int previousStep;  //用于记录之前的步数
    private boolean isNewDay = false; //用于判断是否是新的一天，如果是新的一天则将之前的步数赋值给previousStep
    //判断是否是正常情况（手机是否重启过）
    private boolean isNormal;

    private int tempData;

//    @Override
//    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
//        initTodayData();
//    }


    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case Constant.MSG_FROM_CLIENT:
                    try {
                        Messenger messenger = msg.replyTo;
                        Message message = Message.obtain(null, Constant.MSG_FROM_SERVER);
                        Bundle bundle = new Bundle();
                        //将现在的步数以消息的形式进行发送
                        bundle.putInt("step", StepDetector.CURRENT_STEP);
                        message.setData(bundle);
                        messenger.send(message);  //发送要返回的消息
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    /*
     * 首次创建服务时，系统将调用此方法来执行一次性设置程序（在调用 onStartCommand() 或 onBind() 之前）。
     * 如果服务已在运行，则不会调用此方法。该方法只被调用一次
     */
    @Override
    public void onCreate() {
        super.onCreate();

        //获得今天的日期
        CURRENTDATE = getTodayDate();
        /*
        判断是否处于正常状态下
         */
        List<NormalStepData> normalStepDataList = LitePal.where("today = ?", CURRENTDATE).find(NormalStepData.class);
        //　如果没有数据说明还是处于正常状态，
        // 不然就是在非正常状态，进入非正常状态之后就按照非正常状态的公式计算步数，直到第二天
        if (normalStepDataList.size() == 0 || normalStepDataList.isEmpty()) {

            isNormal = true;
        } else {
            isNormal = false;
        }

        //初始化广播
        intiBroadcastReceiver();

        new Thread(new Runnable() {
            @Override
            public void run() {
                //启动步数检测器
                startStepDetector();
            }
        }).start();
        startTimeCount();

    }

    //每次通过startService()方法启动Service时都会被回调。
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        initTodayData();
        updateNotification("今日步数" + StepDetector.CURRENT_STEP + " 步");

        return START_STICKY;
    }

    //获得今日的日期
    private String getTodayDate() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(date);
    }

    //初始化当前的日期
    private void initTodayData() {
        //Toast.makeText(StepService.this, "initTodayData", Toast.LENGTH_SHORT).show();
        CURRENTDATE = getTodayDate();
        //在创建方法中有判断，如果数据库已经创建了，不会二次创建的
        //DbUtils.createDb();


        //获取当天的数据
        List<StepData> list = LitePal.where("today = ?", CURRENTDATE).find(StepData.class);
        if (list.size() == 0 || list.isEmpty()) {
            //如果获取当天的数据为空，则步数为0
            StepDetector.CURRENT_STEP = 0;
            isNewDay = true;  //用于判断是否存储之前的数据，后面会用到
            isNormal = true;
        } else if (list.size() == 1) {
            isNewDay = false;
            //如果数据库中存在当天的数据那么获取数据库中的步数
            StepDetector.CURRENT_STEP = Integer.parseInt(list.get(0).getStep());
        } else {
            Log.e(TAG, "出错了");
        }
    }

    //初始化广播
    private void intiBroadcastReceiver() {

        //定义意图过滤器
        final IntentFilter intentFilter = new IntentFilter();
        //屏幕灭屏广播
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        //日期修改
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        //关闭广播
        intentFilter.addAction(Intent.ACTION_SHUTDOWN);
        //屏幕高亮广播
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        //屏幕解锁广播
        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
        //当长按电源键弹出“关机”对话或者锁屏时系统会发出这个广播
        //example：有时候会用到系统对话框，权限可能很高，会覆盖在锁屏界面或者“关机”对话框之上，
        //所以监听这个广播，当收到时就隐藏自己的对话，如点击pad右下角部分弹出的对话框
        intentFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

        intentFilter.addAction(Intent.ACTION_TIME_TICK);

        mBatInfoReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (Intent.ACTION_SCREEN_ON.equals(action)) {
                    Log.v(TAG, "screen on");
                } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                    Log.v(TAG, "SCREEN OFF");
                    save();
                    duration = 60000;
                } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                    Log.v(TAG, "SCREEN UNLOCK");
                    save();
                    duration = 5000;
                } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
                    Log.v(TAG, "receive Intent.ACTION_CLOSE_SYSTEM_DIALOGS  出现系统对话框");
                    //保存一次
                    save();
                } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
                    Log.v(TAG, "receive ACTION_SHUTDOWN");
                    save();
                } else if (Intent.ACTION_TIME_CHANGED.equals(action)) {  //ACTION_TIME_CHANGED 手动修改设置里的时间才会发出该广播
                    Log.v(TAG, "receive ACTION_TIME_CHANGED");
                    //initTodayData();
                    isNewDay();
                    save();
                } else if (Intent.ACTION_TIME_TICK.equals(action)) {
                    isNewDay();
                    save();
                }
            }
        };
        registerReceiver(mBatInfoReceiver, intentFilter);
    }

    /**
     * 监听晚上0点变化初始化数据
     */
    private void isNewDay() {
        String time = "00:00";
        if (time.equals(new SimpleDateFormat("HH:mm").format(new Date())) || !CURRENTDATE.equals(getTodayDate())) {
            initTodayData();

        }
    }

    private void startTimeCount() {
        timeCount = new TimeCount(duration, 5000);
        timeCount.start();

    }

    //更新通知（显示通知栏信息
    private void updateNotification(String content) {
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= 26) {
            String id = "default";
            NotificationChannel notificationChannel = new NotificationChannel("default", "TangYee", NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(notificationChannel);
            builder = new NotificationCompat.Builder(this, id);
        } else {
            builder = new NotificationCompat.Builder(this, "default");
        }

        //设置优先级
        builder.setPriority(Notification.PRIORITY_MAX);
        //ＰendingIntent 等待的，未决定的intent
        //getActivity 跳转到一个activity组件
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, StepActivity.class), 0);
        //设置点击之后跳到MainActivity
        builder.setContentIntent(pendingIntent);
        //设置通知栏的图标
        builder.setSmallIcon(R.mipmap.appicon);

        builder.setTicker("糖家");
        builder.setContentTitle("糖家");
        //设置不可清除
        builder.setOngoing(true);
        //设置显示的内容
        builder.setContentText(content);
        Notification notification = builder.build(); //上面的均为构造Notification的构造器中设置的属性
        startForeground(0, notification);

        notificationManager.notify(R.string.app_name, notification);
    }

    //绑定服务时才会调用
    //必须要实现的方法
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }

    //步数检测器
    private void startStepDetector() {
        if (sensorManager != null && stepDetector != null) {
            sensorManager.unregisterListener(stepDetector);
            sensorManager = null;
            stepDetector = null;
        }
        //得到休眠锁，目的是为了当手机黑屏时仍然保持CPU运行，使得服务能持续运行
        getLock(this);
        sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
        //ANDORID4.4以后可以使用计步传感器
        int VERSION_CODES = Build.VERSION.SDK_INT;
        if (VERSION_CODES >= 19) {
            addCountStepListener();
        } else {
            addBasePedoListener();
        }
    }

    private void addCountStepListener() {
        Sensor detectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
        if (countSensor != null) {
            stepSensor = 0;
            Log.v(TAG, "countSensor 步数传感器");
            //注册传感器
            sensorManager.registerListener(StepService.this, countSensor,
                    SensorManager.SENSOR_DELAY_UI);
        } else if (detectorSensor != null) {
            stepSensor = 1;
            Log.v("base", "detector");
            //注册传感器
            sensorManager.registerListener(StepService.this, detectorSensor,
                    SensorManager.SENSOR_DELAY_UI);
        } else {
            stepSensor = 2;
            Log.e(TAG, "Count sensor not available! 没有可用的传感器，只能用加速传感器了");
            addBasePedoListener();

        }
    }

    //使用加速度传感器
    private void addBasePedoListener() {
        //只有在使用加速度传感器的时候才会调用StepDetector这个类
        stepDetector = new StepDetector(this);
        //获取传感器类型，这里获取的类型是加速度传感器
        //此方法用来注册，只有注册过才会生效，参数：SensorEventListener的实例，Sensor的实例，更新速率
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(stepDetector, sensor, SensorManager.SENSOR_DELAY_UI);
        stepDetector.setOnSensorChangeListener(new StepDetector.OnSensorChangeListener() {
            @Override
            public void onChange() {
                updateNotification("今日步数：" + StepDetector.CURRENT_STEP + " 步");
            }

        });
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        if (stepSensor == 0) {  //使用计步传感器
            if (isNewDay) {
                //用于判断是否为新的一天，如果是那么记录下计步传感器统计步数中的数据
                //今天走的步数 = 传感器当前统计的步数 - 之前的步数
                previousStep = (int) event.values[0];  //得到传感器统计的步数
                isNewDay = false;
                save();
                //为防止在previousStep赋值之前数据库就进行了保存，我们将数据库的信息更新一下
                List<StepData> list = LitePal.where("today = ?", CURRENTDATE).find(StepData.class);
                //修改数据
                StepData data = list.get(0);
                data.setPreviousStep(previousStep + "");
                data.updateAll("today= ?", CURRENTDATE);

            } else {
                //取出之前的数据
                List<StepData> list = LitePal.where("today = ?", CURRENTDATE).find(StepData.class);
                StepData data = list.get(0);
                this.previousStep = Integer.valueOf(data.getPreviousStep());
            }
            //手机重启之后，计步传感器的值会归零，为了不出现负数，故采用如下语句进行判断
            if (((int) event.values[0] - previousStep >= 0) && isNormal == true) {
                StepDetector.CURRENT_STEP = (int) event.values[0] - previousStep;
            } else {
                isNormal = false;
                List<StepData> list = LitePal.where("today = ?", CURRENTDATE).find(StepData.class);
                StepData data = list.get(0);
                if (Integer.valueOf(data.getStep()) == 0) {
                    previousStep = 0;
                    data.setPreviousStep(previousStep + "");
                    data.updateAll("today = ?", CURRENTDATE);
                    StepDetector.CURRENT_STEP = (int) event.values[0] - previousStep;
                } else {
                    if (Integer.valueOf(data.getPreviousStep()) != 0) {
//                        final int tempData = Integer.valueOf(data.getStep());
//                        if (tempData == -1) {
//                            tempData = Integer.valueOf(data.getStep());
//
//                        }
                        NormalStepData normalStepData;
                        List<NormalStepData> normalStepDataList = LitePal.where("today = ?", CURRENTDATE).find(NormalStepData.class);
                        if (normalStepDataList.size() == 0 || normalStepDataList.isEmpty()) {
                            normalStepData = new NormalStepData();
                            normalStepData.setToday(CURRENTDATE);
                            normalStepData.setStepNumber(data.getStep());
                            normalStepData.save();
                            tempData = Integer.valueOf(normalStepData.getStepNumber());
                        } else {
                            normalStepData = normalStepDataList.get(0);
                            tempData = Integer.valueOf(normalStepData.getStepNumber());
                        }
                        StepDetector.CURRENT_STEP = (int)event.values[0] + tempData;
                    } else {
                        StepDetector.CURRENT_STEP = (int) event.values[0] - Integer.valueOf(data.getPreviousStep());
                    }
                }

            }


            /*if ((int) event.values[0] - previousStep >= 0) {
                StepDetector.CURRENT_STEP = (int) event.values[0] - previousStep;
            } else {
                List<StepData> list = LitePal.where("today = ?", CURRENTDATE).find(StepData.class);
                StepData data = list.get(0);
                Log.d(TAG, "onSensorChanged: " + data);
                previousStep = 0;
                data.setPreviousStep(previousStep + "");
                data.setStep((Integer.valueOf(data.getStep()) + (int)event.values[0] - previousStep) + "");
                data.updateAll("today = ?", CURRENTDATE);
                StepDetector.CURRENT_STEP = (int) event.values[0] - previousStep;
            }*/


            //或者只是使用下面一句话，不过程序关闭后可能无法计步。根据需求可自行选择。
            //如果记录程序开启时走的步数可以使用这种方式——StepDetector.CURRENT_STEP++;
            //StepDetector.CURRENT_STEP++;
        } else if (stepSensor == 1) {
            if ((int) event.values[0] == 1) {
                StepDetector.CURRENT_STEP++;
            }
        }

        //更新状态栏信息
        updateNotification("今日步数：" + StepDetector.CURRENT_STEP + " 步");

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    //保存数据
    private void save() {

        int tempStep = StepDetector.CURRENT_STEP;

        StepData data = new StepData();
        List<StepData> list = LitePal.where("today = ?", CURRENTDATE).find(StepData.class);
        if (list.size() == 0 || list.isEmpty()) {
            data.setToday(CURRENTDATE);
            data.setStep(tempStep + "");
            data.setPreviousStep(previousStep + "");
            data.save();
        } else if (list.size() == 1) {
            //修改数据
            data.setStep(tempStep + "");
            data.updateAll("today = ?", CURRENTDATE);
        }
    }

    /**
     * 服务销毁时的回调
     */
    @Override
    public void onDestroy() {

        //取消前台进程
        stopForeground(true);
        //DbUtils.closedDb();
        unregisterReceiver(mBatInfoReceiver);
        Intent intent = new Intent(this, StepService.class);
        startService(intent);
        super.onDestroy();
    }

    synchronized private PowerManager.WakeLock getLock(Context context) {
        if (wakeLock != null) {
            if (wakeLock.isHeld()) {
                wakeLock.release();
            }
            wakeLock = null;
        }

        if (wakeLock == null) {
            PowerManager manager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            wakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, StepService.class.getName());
            wakeLock.setReferenceCounted(true);
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis((System.currentTimeMillis()));
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            if (hour >= 23 || hour <= 6) {
                wakeLock.acquire(5000);
            } else {
                wakeLock.acquire(300000);
            }

        }
        return (wakeLock);

    }


    class TimeCount extends CountDownTimer {
        public TimeCount(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);

        }

        @Override
        public void onTick(long millisUntilFinished) {

        }

        @Override
        public void onFinish() {
            //如果计时器正常结束，则开始计步
            timeCount.cancel();
            save();
            startTimeCount();
        }

    }
}
